package presentation;

import javax.swing.*;

import application.decryption.DecryContext;
import application.decryption.DecryptedInfo1;
import application.decryption.DecryptedInfo2;
import application.decryption.DecryptedInfo3;
import application.decryption.Decryption;
import application.encryption.EncryContext;
import application.encryption.EncryptedInfo1;
import application.encryption.EncryptedInfo2;
import application.encryption.EncryptedInfo3;
import application.encryption.Encryption;

import java.awt.event.*;
import java.awt.*;

public class ClientGUI extends JPanel {
    private static final long serialVersionUID = 5308592703759777481L;

    private JSplitPane splitPane;
    private JScrollPane btnPane, resultPane;
    private JPanel buttonPanel;
    private JTextField txtFirstName, txtLastName, txtCode;
    private JLabel lblFirstName, lblLastName, lblCode, lblEncryptMethod; // ,lblLogMethod;
    private JComboBox<String> cmbEncryptMethod;
    private JButton encryBtn, decryBtn, exitButton;
    private static final String ENCRYPT = "Encrypt";
    private static final String DECRYPT = "Decrypt";
    private static final String EXIT = "Exit";
    private static final String FOLDENCRYPTION = "Folding Encryption";
    private static final String BIDIRSHIFTENCRYPTION = "BiShift Encryption";
    private static final String CAESEAENCRYPTION = "Caesea Encryption";
    private static final Dimension minimumSize = new Dimension(400, 300);

    public static final JTextArea resultTxt = new JTextArea("Encrypted Text\n\n", 6, 20);

    public ClientGUI() {

        super(new GridLayout(1, 0));
        txtFirstName = new JTextField(12);
        txtLastName = new JTextField(12);
        txtCode = new JTextField(12);

        cmbEncryptMethod = new JComboBox<>();
        cmbEncryptMethod.addItem(FOLDENCRYPTION);
        cmbEncryptMethod.addItem(BIDIRSHIFTENCRYPTION);
        cmbEncryptMethod.addItem(CAESEAENCRYPTION);

        lblFirstName = new JLabel("First Name:");
        lblLastName = new JLabel("Last Name:");
        lblCode = new JLabel("Agent Code:");
        lblEncryptMethod = new JLabel("Encryption Method:");

        // Create button objects
        encryBtn = new JButton(ENCRYPT);
        encryBtn.setMnemonic(KeyEvent.VK_V);
        decryBtn = new JButton(DECRYPT);
        decryBtn.setMnemonic(KeyEvent.VK_V);
        exitButton = new JButton(EXIT);
        exitButton.setMnemonic(KeyEvent.VK_X);

        JPanel buttonPanel = new JPanel();

        buttonPanel.add(encryBtn);
        buttonPanel.add(decryBtn);
        buttonPanel.add(exitButton);
        buttonPanel.add(lblFirstName);
        buttonPanel.add(txtFirstName);
        buttonPanel.add(lblLastName);
        buttonPanel.add(txtLastName);
        buttonPanel.add(lblCode);
        buttonPanel.add(txtCode);
        buttonPanel.add(lblEncryptMethod);
        buttonPanel.add(cmbEncryptMethod);

        buildUpScrollGUI();
    }

    private void buildUpScrollGUI() {
        // Setup buttonPanel, which contains all buttons and
        // will be used in btnPane below
        setUpButtonPanel();

        btnPane = new JScrollPane(buttonPanel);
        btnPane.setMinimumSize(minimumSize);

        resultPane = new JScrollPane(resultTxt);
        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        splitPane.setLeftComponent(btnPane);
        splitPane.setRightComponent(resultPane);

        splitPane.setDividerLocation(320);
        splitPane.setPreferredSize(new Dimension(600, 250));

        add(splitPane);
        setSize(new Dimension(600, 400));
        setVisible(true);
    }

    private void setUpButtonPanel() {
        // Create buttons and add action Listener
        ButtonListener btnListener = new ButtonListener();
        encryBtn.addActionListener(btnListener);
        decryBtn.addActionListener(btnListener);
        exitButton.addActionListener(btnListener);

        buttonPanel = new JPanel();

        GridBagLayout gridbag = new GridBagLayout();
        buttonPanel.setLayout(gridbag);
        GridBagConstraints gbc = new GridBagConstraints();

        buttonPanel.add(lblFirstName);
        buttonPanel.add(txtFirstName);
        buttonPanel.add(lblLastName);
        buttonPanel.add(txtLastName);
        buttonPanel.add(lblCode);
        buttonPanel.add(txtCode);
        buttonPanel.add(lblEncryptMethod);
        buttonPanel.add(cmbEncryptMethod);
        buttonPanel.add(encryBtn);
        buttonPanel.add(decryBtn);
        buttonPanel.add(exitButton);

        gbc.insets.top = 5;
        gbc.insets.bottom = 5;
        gbc.insets.left = 5;
        gbc.insets.right = 5;

        gbc.anchor = GridBagConstraints.WEST;

        gbc.gridx = 0;
        gbc.gridy = 0;
        gridbag.setConstraints(lblFirstName, gbc);
        gbc.gridx = 1;
        gbc.gridy = 0;
        gridbag.setConstraints(txtFirstName, gbc);
        gbc.gridx = 0;
        gbc.gridy = 1;
        gridbag.setConstraints(lblLastName, gbc);
        gbc.gridx = 1;
        gbc.gridy = 1;
        gridbag.setConstraints(txtLastName, gbc);
        gbc.gridx = 0;
        gbc.gridy = 2;
        gridbag.setConstraints(lblCode, gbc);
        gbc.gridx = 1;
        gbc.gridy = 2;
        gridbag.setConstraints(txtCode, gbc);
        gbc.gridx = 0;
        gbc.gridy = 3;
        gridbag.setConstraints(lblEncryptMethod, gbc);
        gbc.gridx = 1;
        gbc.gridy = 3;
        gridbag.setConstraints(cmbEncryptMethod, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 0;
        gbc.gridy = 5;
        gridbag.setConstraints(encryBtn, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 1;
        gbc.gridy = 5;
        gridbag.setConstraints(decryBtn, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 2;
        gbc.gridy = 5;
        gridbag.setConstraints(exitButton, gbc);
    }

    public String getFirstName() {
        return txtFirstName.getText();
    }

    public String getLastName() {
        return txtLastName.getText();
    }

    public String getCode() {
        return txtCode.getText();
    }

    public String getEncryptMethod() {
        return (String) cmbEncryptMethod.getSelectedItem();
    }

    /* ========================================= */
    class ButtonListener implements ActionListener {
        ClientGUI objClientGUI;
        Encryption info;
        Decryption decryption;

        public void actionPerformed(ActionEvent e) {
            String encryptWay;
            switch (e.getActionCommand()) {
            case ENCRYPT:
                String firstNm = getFirstName();
                String lastNm = getLastName();
                String code = getCode();
                encryptWay = getEncryptMethod();

                if (encryptWay.equals(FOLDENCRYPTION)) {
                    info = new EncryptedInfo1();
                } else if (encryptWay.equals(BIDIRSHIFTENCRYPTION)) {
                    info = new EncryptedInfo2();
                } else if (encryptWay.equals(CAESEAENCRYPTION)) {
                    info = new EncryptedInfo3();
                }

                // info.log(lastNm, firstNm, code, resultTxt);

                new EncryContext(info).doEncryption(lastNm, firstNm, code, resultTxt);
                break;

            case DECRYPT:
                encryptWay = getEncryptMethod();
                if (encryptWay.equals(FOLDENCRYPTION)) {
                    decryption = new DecryptedInfo1();
                } else if (encryptWay.equals(BIDIRSHIFTENCRYPTION)) {
                    decryption = new DecryptedInfo2();
                } else if (encryptWay.equals(CAESEAENCRYPTION)) {
                    decryption = new DecryptedInfo3();
                }
                new DecryContext(decryption).doDecryption(resultTxt);
                break;
            case EXIT:
                System.exit(1);
            }
        }

        public ButtonListener() {

        }

        public ButtonListener(ClientGUI inObjClientGUI) {
            objClientGUI = inObjClientGUI;
        }

    }

    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Bridge Pattern - Encryption");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ClientGUI newContentPane = new ClientGUI();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    static public void main(String[] argv) {
        javax.swing.SwingUtilities.invokeLater(ClientGUI::createAndShowGUI);
    }
}
